##
# @configure_input@
#
# make fortran_wrapper.c
##

export SRCDIR=@top_vt_srcdir@/config/mpigen

export COMM_CONVERT=@VT_MPIGEN_HAVE_FC_CONV_COMM@
export ERRH_CONVERT=@VT_MPIGEN_HAVE_FC_CONV_ERRH@
export FILE_CONVERT=@VT_MPIGEN_HAVE_FC_CONV_FILE@
export GROUP_CONVERT=@VT_MPIGEN_HAVE_FC_CONV_GROUP@
export INFO_CONVERT=@VT_MPIGEN_HAVE_FC_CONV_INFO@
export OP_CONVERT=@VT_MPIGEN_HAVE_FC_CONV_OP@
export REQUEST_CONVERT=@VT_MPIGEN_HAVE_FC_CONV_REQUEST@
export STATUS_CONVERT=@VT_MPIGEN_HAVE_FC_CONV_STATUS@
export TYPE_CONVERT=@VT_MPIGEN_HAVE_FC_CONV_TYPE@
export WIN_CONVERT=@VT_MPIGEN_HAVE_FC_CONV_WIN@
export MPI2CONST_CONVERT=@VT_MPIGEN_HAVE_FC_CONV_MPI2CONST@

have_mpi2_thread=@VT_MPIGEN_HAVE_MPI2_THREAD@
have_mpi2_1sided=@VT_MPIGEN_HAVE_MPI2_1SIDED@
have_mpi2_extcoll=@VT_MPIGEN_HAVE_MPI2_EXTCOLL@
have_mpi2_file=@VT_MPIGEN_HAVE_MPI2_IO@
have_mpi2_proc=0 #@VT_MPIGEN_HAVE_MPI2_PROC@
have_mpi2=0
if [ $have_mpi2_thread = 1 -o $have_mpi2_1sided = 1 -o $have_mpi2_extcoll = 1 -o $have_mpi2_proc = 1 ] ; then
  have_mpi2=1
fi
mpi2_src1=""; if [ $have_mpi2 = 1 ] ; then mpi2_src1="mpi2_standard.h"; fi
mpi2_src2=""; if [ $have_mpi2_thread = 1 ] ; then mpi2_src2="mpi2_thread.h"; fi
mpi2_src3=""; if [ $have_mpi2_1sided = 1 ] ; then mpi2_src3="mpi2_1sided.h"; fi
mpi2_src4=""; if [ $have_mpi2_extcoll = 1 ] ; then mpi2_src4="mpi2_extcoll.h"; fi
mpi2_src5=""; if [ $have_mpi2_file = 1 ] ; then mpi2_src5="mpi2_file.h"; fi
mpi2_src6=""; if [ $have_mpi2_proc = 1 ] ; then mpi2_src6="mpi2_proc.h"; fi
src="mpi_standard.h $mpi2_src1 $mpi2_src2 $mpi2_src3 $mpi2_src4 $mpi2_src5 $mpi2_src6"

out=@top_vt_builddir@/vtlib/vt_fmpiwrap.gen.c
tmp=tmp$$
trap "rm -f $tmp.*; exit" 0 1 2 3 15

rm -f $tmp.tmp $out
for s in $src; do
  if [ ! -f $SRCDIR/$s ] ; then
    echo "$0: error: $SRCDIR/$s not found!"
    exit 1
  fi

  grep ' MPI_.*(.*)' $SRCDIR/$s \
  | sed >>$tmp.tmp \
    -e '/typedef /d' \
    -e 's/( *void *)/()/' \
    -e 's/   */ /g' \
    -e 's/ /,/' \
    -e 's/(/,/' \
    -e 's/);//' \
    -e 's/, /,/g' \
    -e 's/,$//'
done

cat <<End-of-File >$tmp.c
/**
 * VampirTrace
 * http://www.tu-dresden.de/zih/vampirtrace
 *
 * Copyright (c) 2005-2012, ZIH, TU Dresden, Federal Republic of Germany
 *
 * Copyright (c) 1998-2005, Forschungszentrum Juelich, Juelich Supercomputing
 *                          Centre, Federal Republic of Germany
 *
 * See the file COPYING in the package base directory for details
 *
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 * ! BUILT BY mk_fortran_wrapper.sh; DO NOT EDIT THIS FILE !
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 **/

End-of-File

cat <<End-of-File >$tmp.awk
{
# Fortran wrapper
#
# \$1 is the return type
# \$2 is the call name
# \$3,\$4,... parameters
  call= "grep -i \\"^"\$2"\$\\" \$SRCDIR/fortran_dont_generate.txt > /dev/null"

  generate=system(call)

  mpicall=\$2

  if (!generate) {
    printf "/* -- %s -- not generated */\n\n", mpicall
    next
  }

  aint_convert=0

  if (index(mpicall,"MPI_Address") != 0 ||
      index(mpicall,"MPI_Type_extent") != 0 ||
      index(mpicall,"MPI_Type_hindexed") != 0 ||
      index(mpicall,"MPI_Type_hvector") != 0 ||
      index(mpicall,"MPI_Type_lb") != 0 ||
      index(mpicall,"MPI_Type_struct") != 0 ||
      index(mpicall,"MPI_Type_ub") != 0)
  {
    aint_convert=1
  }

  optional=0

  if (index(mpicall,"MPI_Add_error_class") != 0) {
    printf "#if defined(HAVE_MPI_ADD_ERROR_CLASS) && HAVE_MPI_ADD_ERROR_CLASS\n\n"
    optional=1
  }
  if (index(mpicall,"MPI_Add_error_code") != 0) {
    printf "#if defined(HAVE_MPI_ADD_ERROR_CODE) && HAVE_MPI_ADD_ERROR_CODE\n\n"
    optional=1
  }
  if (index(mpicall,"MPI_Add_error_string") != 0) {
    printf "#if defined(HAVE_MPI_ADD_ERROR_STRING) && HAVE_MPI_ADD_ERROR_STRING\n\n"
    optional=1
  }
  if (index(mpicall,"MPI_Type_create_f90_complex") != 0) {
    printf "#if defined(HAVE_MPI_TYPE_CREATE_F90_COMPLEX) && HAVE_MPI_TYPE_CREATE_F90_COMPLEX\n\n"
    optional=1
  }
  if (index(mpicall,"MPI_Type_create_f90_integer") != 0) {
    printf "#if defined(HAVE_MPI_TYPE_CREATE_F90_INTEGER) && HAVE_MPI_TYPE_CREATE_F90_INTEGER\n\n"
    optional=1
  }
  if (index(mpicall,"MPI_Type_create_f90_real") != 0) {
    printf "#if defined(HAVE_MPI_TYPE_CREATE_F90_REAL) && HAVE_MPI_TYPE_CREATE_F90_REAL\n\n"
    optional=1
  }
  if (index(mpicall,"MPI_Type_match_size") != 0) {
    printf "#if defined(HAVE_MPI_TYPE_MATCH_SIZE) && HAVE_MPI_TYPE_MATCH_SIZE\n\n"
    optional=1
  }
  if (index(mpicall,"MPI_Win_test") != 0) {
    printf "#if defined(HAVE_PMPI_WIN_TEST) && HAVE_PMPI_WIN_TEST\n\n"
    optional=1
  }
  if (index(mpicall,"MPI_Win_lock") != 0) {
    printf "#if defined(HAVE_PMPI_WIN_LOCK) && HAVE_PMPI_WIN_LOCK\n\n"
    optional=1
  }
  if (index(mpicall,"MPI_Win_unlock") != 0) {
    printf "#if defined(HAVE_PMPI_WIN_UNLOCK) && HAVE_PMPI_WIN_UNLOCK\n\n"
    optional=1
  }
  if (index(mpicall,"MPI_Register_datarep") != 0) {
    printf "#if defined(HAVE_MPI_REGISTER_DATAREP) && HAVE_MPI_REGISTER_DATAREP\n\n"
    optional=1
  }

  stringcnt=0

  printf "/* -- %s -- */\n\n", mpicall

  printf "VT_DECLDEF(void vt_%s_f(", tolower(mpicall)

  if (NF == 2) {
    printf "MPI_Fint* ierr"
  } else {
    for (i=3; i<=NF; i++) {
      # Split up the type and parameter-name -- separated by space and tab
      split(\$i,typeandpara," ")
      type[i-2]=typeandpara[1]
      para[i-2]=typeandpara[2]
      if (i > 3) printf ", "
      if (type[i-2] == "char*") {
        strings[stringcnt++] = para[i-2]
        printf "%s %s", type[i-2], para[i-2]
      } else if (index(type[i-2], "*") != 0 || index(para[i-2], "[") != 0) {
        printf "%s %s", converttype(type[i-2]), para[i-2]
      } else {
        printf "%s* %s", converttype(type[i-2]), para[i-2]
      }
    }
    printf ", MPI_Fint* ierr"
    for (i=0; i<stringcnt; i++) {
      printf ", int %s_len", strings[i]
    }
  }

  print "))"
  print "{"

  # do the handle conversion, if possible
  # first, declare necessary variables
  decl_i=0
  for (i=3; i<=NF; i++) {
    print_convert_function(type[i-2],para[i-2],1)
    if ((!decl_i) && (index(para[i-2],"_CLASS_ARRAY_") != 0)) decl_i=1
  }
  if (decl_i == 1) print "  int i = 0; (void)i;"
  print "";

  # print special conversion line for MPI_Waitsome, MPI_Testsome
  # For these calls it is necessary to allocate an amount of statuses
  # equal to the value speciefied in incount and to convert as many 
  # statuses as defined by the return value outcount. In order to avoid
  # special handling the initial value for outcount is set to the value 
  # of incount.
  if ( (index(mpicall,"MPI_Waitsome") != 0) ||
       (index(mpicall,"MPI_Testsome") != 0) )
  {
    print "  *outcount = *incount;"
  }

  # do the handle conversion
  for (i=3; i<=NF; i++)
    print_convert_function(type[i-2],para[i-2],0)
  print ""

  print  "  VT_UNIMCI_SET_BINDING_LANGUAGE_FORTRAN();"
  printf "  *ierr = %s(", mpicall
  for (i=3; i<=NF; i++) {
    if (i > 3) printf ", "
    # If the original type already needed a pointer, pass as is,
    # otherwise dereference the parameter
    printf "%s", get_converted_name(para[i-2],type[i-2])
  }
  print ");"
  print "  VT_UNIMCI_SET_BINDING_LANGUAGE_C();"
  print ""

  # finaly do the handle back conversion if possible/necessary
  for (i=3; i<=NF; i++)
    print_back_convert_function(type[i-2],para[i-2])

  # also dont forget to do convert output array indices 
  for (i=3; i<=NF; i++)
    convert_output_array_indices(type[i-2],para[i-2])

  printf "} VT_GENERATE_F77_BINDINGS(%s, %s, vt_%s_f,\n", tolower(mpicall), toupper(mpicall), tolower(mpicall)

  printf "  ("
  if (NF == 2) {
    print "MPI_Fint* ierr),"
  } else {
    for (i=3; i<=NF; i++) {
      if (i > 3) printf ", "
      if (index(type[i-2], "*") != 0 || index(para[i-2], "[") != 0)
        printf "%s %s", converttype(type[i-2]), para[i-2]
      else
        printf "%s* %s", converttype(type[i-2]), para[i-2]
    }
    printf ", MPI_Fint* ierr"
    for (i=0; i<stringcnt; i++) {
      printf ", int %s_len", strings[i]
    }
    print "),"
  }

  printf "  ("
  if (NF == 2) {
    printf "ierr))\n\n"
  } else {
    for (i=3; i<=NF; i++) {
      if (i > 3) printf ", "
      #remove arrays declarations from parameter:
      gsub("[[].*[]]","",para[i-2])
      # If the original type already needed a pointer, pass as is,
      # otherwise dereference the parameter
      printf "%s", para[i-2]
    }
    printf ", ierr"
    for (i=0; i<stringcnt; i++) {
      printf ", %s_len", strings[i]
    }
    printf "))\n\n"
  }

  if (optional) {
    printf "#endif\n\n"
  }
}

# =================================================
#    Helper Functions for Conversion mangling
# =================================================

# -------------------------------------------------
# Function converts types. It replaces MPI_X Types
# by MPI_Fint.
# -------------------------------------------------
function converttype(type) { 
  if (aint_convert)
    gsub("MPI_Aint","MPI_Fint",type)

  if (ENVIRON["COMM_CONVERT"] == 1)
    gsub("MPI_Comm","MPI_Fint",type)

  if (ENVIRON["ERRH_CONVERT"] == 1)
    gsub("MPI_Errhandler","MPI_Fint",type)

  if (ENVIRON["FILE_CONVERT"] == 1)
    gsub("MPI_File","MPI_Fint",type)

  if (ENVIRON["GROUP_CONVERT"] == 1)
    gsub("MPI_Group","MPI_Fint",type)

  if (ENVIRON["INFO_CONVERT"] == 1)
    gsub("MPI_Info","MPI_Fint",type)

  if (ENVIRON["OP_CONVERT"] == 1)
    gsub("MPI_Op","MPI_Fint",type)

  if (ENVIRON["TYPE_CONVERT"] == 1)
    gsub("MPI_Datatype","MPI_Fint",type)

  if (ENVIRON["WIN_CONVERT"] == 1)
    gsub("MPI_Win","MPI_Fint",type)

  if (ENVIRON["REQUEST_CONVERT"] == 1)
    gsub("MPI_Request","MPI_Fint",type)

  gsub("MPI_Status","MPI_Fint",type)

  return type
}

# -------------------------------------------------
# Function creating temporary variables and 
# converting Fortran variables to C variables
# -------------------------------------------------
function print_convert_function(type,para,decl) {

    # a SINGLE value for input purposes
    if ( (index(type,"*") == 0) ||
         ((index(para, "_CLASS_SINGLE_IN") != 0) ||
          (index(para, "_CLASS_SINGLE_IO") != 0)) )
    {
        #all of these classes need temp parameter and conversion
        pointer="*"

        if (type == "char*") {
            if (decl) printf"  char* %sC = NULL;\n", para
            else printf"  vt_string_f2c(%s, %s_len, &%sC);\n", para, para, para 
        } else if (aint_convert && (index(type,"MPI_Aint")) > 0) {
            if (decl) printf"  MPI_Aint %sC;\n",para
            else printf"  %sC = (MPI_Aint)%s%s;\n",para,pointer,para
        } else if ((ENVIRON["COMM_CONVERT"] == 1) && (index(type,"MPI_Comm") > 0)) {
            if (decl) printf"  MPI_Comm %sC;\n", para
            else printf"  %sC = MPI_Comm_f2c(%s%s);\n",para,pointer,para
        } else if ((ENVIRON["ERRH_CONVERT"] == 1) && (index(type,"MPI_Errhandler") > 0)) {
            if (decl) printf"  MPI_Errhandler %sC;\n", para
            else printf"  %sC = MPI_Errhandler_f2c(%s%s);\n",para,pointer,para
        } else if ((ENVIRON["FILE_CONVERT"] == 1) && (index(type,"MPI_File") > 0)) {
            if (decl) printf"  MPI_File %sC;\n", para
            else printf"  %sC = MPI_File_f2c(%s%s);\n",para,pointer,para
        } else if ((ENVIRON["GROUP_CONVERT"] == 1) && (index(type,"MPI_Group") > 0)) {
            if (decl) printf"  MPI_Group %sC;\n", para
            else printf"  %sC = MPI_Group_f2c(%s%s);\n",para,pointer,para
        } else if ((ENVIRON["INFO_CONVERT"] == 1) && (index(type,"MPI_Info") > 0)) {
            if (decl) printf"  MPI_Info %sC;\n", para
            else printf"  %sC = MPI_Info_f2c(%s%s);\n",para,pointer,para
        } else if ((ENVIRON["OP_CONVERT"] == 1) && (index(type,"MPI_Op") > 0)) {
            if (decl) printf"  MPI_Op %sC;\n", para
            else printf"  %sC = MPI_Op_f2c(%s%s);\n",para,pointer,para
        } else if ((ENVIRON["TYPE_CONVERT"] == 1) && (index(type,"MPI_Datatype") > 0)) {
            if (decl) printf"  MPI_Datatype %sC;\n", para
            else printf"  %sC = MPI_Type_f2c(%s%s);\n",para,pointer,para
        } else if ((ENVIRON["WIN_CONVERT"] == 1) && (index(type,"MPI_Win") > 0)) {
            if (decl) printf"  MPI_Win %sC;\n", para
            else printf"  %sC = MPI_Win_f2c(%s%s);\n",para,pointer,para
        } else if ((ENVIRON["REQUEST_CONVERT"] == 1) && (index(type,"MPI_Request") > 0)) {
            if (decl) printf"  MPI_Request %sC;\n", para
            else printf"  %sC = MPI_Request_f2c(%s%s);\n",para,pointer,para
        } else if (index(type,"MPI_Status") > 0) {
            if (decl) {
                printf"  MPI_Status* %sC;\n", para
            } else {
                printf"  if ( %s == VT_MPI_F_STATUS_IGNORE )\n",para
                printf"    %sC = MPI_STATUS_IGNORE;\n",para
                printf"  else if ( %s == VT_MPI_F_STATUSES_IGNORE )\n",para
                printf"    %sC = MPI_STATUSES_IGNORE;\n",para
                printf"  else\n  {\n"
                if (ENVIRON["STATUS_CONVERT"] == 1) {
                   printf"    %sC = (MPI_Status*)malloc(sizeof(MPI_Status));\n",para
                   printf"    MPI_Status_f2c(%s, %sC);\n",para,para
                } else {
                   printf"    %sC = (MPI_Status*)%s;\n",para,para
                }
                printf"  }\n"
            }
        }
    # a SINGLE value for output purposes
    } else if ( index(para, "_CLASS_SINGLE_OUT") != 0) {
        #Here we just need to create an temp parameter

        if (type == "char*") {
            if (decl) printf "  char %sC[1024];\n", para
        } else if (aint_convert && (index(type,"MPI_Aint") > 0)) {
            if (decl) printf"  MPI_Aint %sC;\n",para
        } else if ((ENVIRON["COMM_CONVERT"] == 1) && (index(type,"MPI_Comm") > 0)) {
            if (decl) printf"  MPI_Comm %sC;\n",para
            else printf"  %sC = MPI_COMM_NULL;\n",para
        } else if ((ENVIRON["ERRH_CONVERT"] == 1) && (index(type,"MPI_Errhandler") > 0)) {
            if (decl) printf"  MPI_Errhandler %sC;\n",para
            else printf"  %sC = MPI_ERRHANDLER_NULL;\n",para
        } else if ((ENVIRON["FILE_CONVERT"] == 1) && (index(type,"MPI_File") > 0)) {
            if (decl) printf"  MPI_File %sC;\n",para
            else printf"  %sC = MPI_FILE_NULL;\n",para
        } else if ((ENVIRON["GROUP_CONVERT"] == 1) && (index(type,"MPI_Group") > 0)) {
            if (decl) printf"  MPI_Group %sC;\n",para
            else printf"  %sC = MPI_GROUP_NULL;\n",para
        } else if ((ENVIRON["INFO_CONVERT"] == 1) && (index(type,"MPI_Info") > 0)) {
            if (decl) printf"  MPI_Info %sC;\n",para
            else printf"  %sC = MPI_INFO_NULL;\n",para
        } else if ((ENVIRON["OP_CONVERT"] == 1) && (index(type,"MPI_Op") > 0)) {
            if (decl) printf"  MPI_Op %sC;\n",para
            else printf"  %sC = MPI_OP_NULL;\n",para
        } else if ((ENVIRON["TYPE_CONVERT"] == 1) && (index(type,"MPI_Datatype") > 0)) {
            if (decl) printf"  MPI_Datatype %sC;\n",para
            else printf"  %sC = MPI_DATATYPE_NULL;\n",para
        } else if ((ENVIRON["WIN_CONVERT"] == 1) && (index(type,"MPI_Win") > 0)) {
            if (decl) printf"  MPI_Win %sC;\n",para
            else printf"  %sC = MPI_WIN_NULL;\n",para
        } else if ((ENVIRON["REQUEST_CONVERT"] == 1) && (index(type,"MPI_Request") > 0)) {
            if (decl) printf"  MPI_Request %sC;\n",para
            else printf"  %sC = MPI_REQUEST_NULL;\n",para
        } else if (index(type,"MPI_Status") > 0) {
            if (decl) {
              printf"  MPI_Status* %sC;\n",para
            } else {
              printf"  if ( %s == VT_MPI_F_STATUS_IGNORE )\n",para
              printf"    %sC = MPI_STATUS_IGNORE;\n",para
              printf"  else if ( %s == VT_MPI_F_STATUSES_IGNORE )\n",para
              printf"    %sC = MPI_STATUSES_IGNORE;\n",para
              printf"  else\n"
              if (ENVIRON["STATUS_CONVERT"] == 1) {
                 printf"    %sC = (MPI_Status*)malloc(sizeof(MPI_Status));\n",para
              } else {
                 printf"    %sC = (MPI_Status*)%s;\n",para,para
              }
            }
        }
    # an ARRAY for input and/or output purposes
    } else if ( (index(para, "_CLASS_ARRAY_") != 0) ) {
        #We need for all array cases a temporary array

        #extract the name of the length parameter
        splitstring="_CLASS_ARRAY_IN_"
        if (index(para, "_CLASS_ARRAY_IO_") != 0)
            splitstring="_CLASS_ARRAY_IO_"
        if (index(para, "_CLASS_ARRAY_OUT_") != 0)
            splitstring="_CLASS_ARRAY_OUT_"

        split(para,lentemp,splitstring)
        len_parameter = lentemp[2]

        #now we have to handle all the imaginable handles
        if (aint_convert && (index(type,"MPI_Aint") > 0)) {
            if (decl) {
                printf"  MPI_Aint* %sC;\n",para
            } else {
                printf"  %sC = (MPI_Aint*)malloc(sizeof(MPI_Aint)*(*%s));\n",para,len_parameter
            }
        } else if ((ENVIRON["COMM_CONVERT"] == 1) && (index(type,"MPI_Comm") > 0)) {
            if (decl) {
                printf"  MPI_Comm* %sC;\n",para
            } else {
                printf"  %sC = (MPI_Comm*)malloc(sizeof(MPI_Comm)*(*%s));\n",para,len_parameter
                printf"  for (i = 0; i < *%s; i++) \n",len_parameter
                printf"    %sC[i] = MPI_COMM_NULL;\n",para        
            }
        } else if ((ENVIRON["ERRH_CONVERT"] == 1) && (index(type,"MPI_Errhandler") > 0)) {
            if (decl) {
                printf"  MPI_Errhandler* %sC;\n",para
            } else {
                printf"  %sC = (MPI_Errhandler*)malloc(sizeof(MPI_Errhandler)*(*%s));\n",para,len_parameter
                printf"  for (i = 0; i < *%s; i++) \n",len_parameter
                printf"    %sC[i] = MPI_ERRHANDLER_NULL;\n",para
            }
        } else if ((ENVIRON["FILE_CONVERT"] == 1) && (index(type,"MPI_File") > 0)) {
           if (decl) {
                printf"  MPI_File* %sC;\n",para
            } else {
                printf"  %sC = (MPI_File*)malloc(sizeof(MPI_File)*(*%s));\n",para,len_parameter
                printf"  for (i = 0; i < *%s; i++) \n",len_parameter
                printf"    %sC[i] = MPI_FILE_NULL;\n",para
            }
        } else if ((ENVIRON["GROUP_CONVERT"] == 1) && (index(type,"MPI_Group") > 0)) {
           if (decl) {
                printf"  MPI_Group* %sC;\n",para
            } else {
                printf"  %sC = (MPI_Group*)malloc(sizeof(MPI_Group)*(*%s));\n",para,len_parameter
                printf"  for (i = 0; i < *%s; i++) \n",len_parameter
                printf"    %sC[i] = MPI_GROUP_NULL;\n",para
            }
        } else if ((ENVIRON["INFO_CONVERT"] == 1) && (index(type,"MPI_Info") > 0)) {
            if (decl) {
                printf"  MPI_Info* %sC;\n",para
            } else {
                printf"  %sC = (MPI_Info*)malloc(sizeof(MPI_Info)*(*%s));\n",para,len_parameter
                printf"  for (i = 0; i < *%s; i++) \n",len_parameter
                printf"    %sC[i] = MPI_INFO_NULL;\n",para
            }
        } else if ((ENVIRON["OP_CONVERT"] == 1) && (index(type,"MPI_Op") > 0)) {
            if (decl) {
                printf"  MPI_Op* %sC;\n",para
            } else {
                printf"  %sC = (MPI_Op*)malloc(sizeof(MPI_Op)*(*%s));\n",para,len_parameter
                printf"  for (i = 0; i < *%s; i++) \n",len_parameter
                printf"    %sC[i] = MPI_OP_NULL;\n",para
            }
        } else if ((ENVIRON["TYPE_CONVERT"] == 1) && (index(type,"MPI_Datatype") > 0)) {
            if (decl) {
                printf"  MPI_Datatype* %sC;\n",para
            } else {
                printf"  %sC = (MPI_Datatype*)malloc(sizeof(MPI_Datatype)*(*%s));\n",para,len_parameter
                printf"  for (i = 0; i < *%s; i++) \n",len_parameter
                printf"    %sC[i] = MPI_DATATYPE_NULL;\n",para
            }
        } else if ((ENVIRON["WIN_CONVERT"] == 1) && (index(type,"MPI_Win") > 0)) {
            if (decl) {
                printf"  MPI_Win* %sC;\n",para
            } else {
                printf"  %sC = (MPI_Win*)malloc(sizeof(MPI_Win)*(*%s));\n",para,len_parameter
                printf"  for (i = 0; i < *%s; i++) \n",len_parameter
                printf"    %sC[i] = MPI_WIN_NULL;\n",para
            }
        } else if ((ENVIRON["REQUEST_CONVERT"] == 1) && (index(type,"MPI_Request") > 0)) {
            if (decl) {
                printf"  MPI_Request* %sC;\n",para
            } else {
                printf"  %sC = (MPI_Request*)malloc(sizeof(MPI_Request)*(*%s));\n",para,len_parameter
                printf"  for (i = 0; i < *%s; i++) \n",len_parameter
                printf"    %sC[i] = MPI_REQUEST_NULL;\n",para
            }
        } else if (index(type,"MPI_Status") > 0) {
            if (decl) {
                printf"  MPI_Status* %sC;\n",para
            } else {
                printf"  if ( %s == VT_MPI_F_STATUSES_IGNORE )\n",para
                printf"    %sC = MPI_STATUSES_IGNORE;\n",para
                printf"  else if ( %s == VT_MPI_F_STATUS_IGNORE )\n",para
                printf"    %sC = MPI_STATUS_IGNORE;\n",para
                printf"  else\n"
                if (ENVIRON["STATUS_CONVERT"] == 1) {
                   printf"    %sC = (MPI_Status*)malloc(sizeof(MPI_Status)*(*%s));\n",para,len_parameter
                } else {
                   printf"    %sC = (MPI_Status*)%s;\n",para,para
                }
            }
        }
    }

    # an ARRAY for input purposes
    if ( (index(para, "_CLASS_ARRAY_IN_") != 0) ||
              (index(para, "_CLASS_ARRAY_IO_") != 0) )
    {
        #both of these classes need temp array parameter and conversion

        #extract the name of the length parameter
        splitstring="_CLASS_ARRAY_IN_"
        if (index(para, "_CLASS_ARRAY_IO_") != 0)
            splitstring="_CLASS_ARRAY_IO_"

        split(para,lentemp,splitstring)
        len_parameter = lentemp[2]

        #now we have to handle all the imaginable handles
        if (aint_convert && (index(type,"MPI_Aint") > 0)) {
            if (!decl) {
                printf"  for (i = 0; i < *%s; i++) \n",len_parameter
                printf"    %sC[i] = (MPI_Aint)%s[i];\n",para,para
            }
        } else if ((ENVIRON["COMM_CONVERT"] == 1) && (index(type,"MPI_Comm") > 0)) {
            if (!decl) {
                printf"  for (i = 0; i < *%s; i++) \n",len_parameter
                printf"    %sC[i] = MPI_Comm_f2c(%s[i]);\n",para,para
            }
        } else if ((ENVIRON["ERRH_CONVERT"] == 1) && (index(type,"MPI_Errhandler") > 0)) {
            if (!decl) {
                printf"  for (i = 0; i < *%s; i++) \n",len_parameter
                printf"    %sC[i] = MPI_Errhandler_f2c(%s[i]);\n",para,para
            }
        } else if ((ENVIRON["FILE_CONVERT"] == 1) && (index(type,"MPI_File") > 0)) {
            if (!decl) {
                printf"  for (i = 0; i < *%s; i++) \n",len_parameter
                printf"    %sC[i] = MPI_File_f2c(%s[i]);\n",para,para
            }
        } else if ((ENVIRON["GROUP_CONVERT"] == 1) && (index(type,"MPI_Group") > 0)) {
            if (!decl) {
                printf"  for (i = 0; i < *%s; i++) \n",len_parameter
                printf"    %sC[i]=MPI_Group_f2c(%s[i]);\n",para,para
            }
        } else if ((ENVIRON["INFO_CONVERT"] == 1) && (index(type,"MPI_Info") > 0)) {
            if (!decl) {
                printf"  for (i = 0; i < *%s; i++) \n",len_parameter
                printf"    %sC[i] = MPI_Info_f2c(%s[i]);\n",para,para
            }
        } else if ((ENVIRON["OP_CONVERT"] == 1) && (index(type,"MPI_Op") > 0)) {
            if (!decl) {
                printf"  for (i = 0; i < *%s; i++) \n",len_parameter
                printf"    %sC[i] = MPI_Op_f2c(%s[i]);\n",para,para
            }
        } else if ((ENVIRON["TYPE_CONVERT"] == 1) && (index(type,"MPI_Datatype") > 0)) {
            if (!decl) {
                printf"  for (i = 0; i < *%s; i++) \n",len_parameter
                printf"    %sC[i] = MPI_Type_f2c(%s[i]);\n",para,para
            }
        } else if ((ENVIRON["WIN_CONVERT"] == 1) && (index(type,"MPI_Win") > 0)) {
            if (!decl) {
                printf"  for (i = 0; i < *%s; i++) \n",len_parameter
                printf"    %sC[i] = MPI_Win_f2c(%s[i]);\n",para,para
            }
        } else if ((ENVIRON["REQUEST_CONVERT"] == 1) && (index(type,"MPI_Request") > 0)) {
            if (!decl) {
                printf"  for (i = 0; i < *%s; i++) \n",len_parameter
                printf"    %sC[i] = MPI_Request_f2c(%s[i]);\n",para,para
            }
        } else if ((ENVIRON["STATUS_CONVERT"] == 1) && (index(type,"MPI_Status") > 0)) {
            if (!decl) {
                printf"  if ( (%s != VT_MPI_F_STATUSES_IGNORE) && (%s != VT_MPI_F_STATUS_IGNORE) )\n  {\n",para,para
                printf"    for (i = 0; i < *%s; i++) \n",len_parameter
                printf"      MPI_Status_f2c(&%s[i], &%sC[i*VT_MPI_STATUS_SIZE]);\n",para,para
                printf"  }\n"
            }
        }
    # a BUFFER for purposes
    } else if ( (index(para, "_CLASS_BUFFER") != 0) ) {
        if (!decl) {
            if ((ENVIRON["MPI2CONST_CONVERT"] == 1) && (index(para, "_IN_PLACE") > 0)) {
                printf"  %s = VT_MPI_IN_PLACE_F2C(%s);\n",para,para
            }
            printf"  %s = VT_MPI_BOTTOM_F2C(%s);\n",para,para
        }
    }
}

# -------------------------------------------------
# Function deleting dynamic temporary variables and 
# back converting C variables to Fortran variables
# -------------------------------------------------
function print_back_convert_function(type,para) {

    # SINGLE ARGUMENT BACK CONVERSION    
    if (  ((index(para, "_CLASS_SINGLE_OUT") != 0) ||
           (index(para, "_CLASS_SINGLE_IO") != 0 ))  )
    {
        #this class needs back conversion of a single argument

        if (type == "char*")
            printf"  vt_string_c2f(%sC, %s, %s_len);\n", para, para, para

	if (aint_convert && (index(type,"MPI_Aint") > 0))
            printf"  *%s = (MPI_Fint)%sC;\n",para,para

        if ((ENVIRON["COMM_CONVERT"] == 1) && (index(type,"MPI_Comm") > 0))
            printf"  *%s = MPI_Comm_c2f(%sC);\n",para,para

        if ((ENVIRON["ERRH_CONVERT"] == 1) && (index(type,"MPI_Errhandler") > 0))
            printf"  *%s = MPI_Errhandler_c2f(%sC);\n",para,para

        if ((ENVIRON["FILE_CONVERT"] == 1) && (index(type,"MPI_File") > 0))
            printf"  *%s = MPI_File_c2f(%sC);\n",para,para

        if ((ENVIRON["GROUP_CONVERT"] == 1) && (index(type,"MPI_Group") > 0))
            printf"  *%s = MPI_Group_c2f(%sC);\n",para,para

        if ((ENVIRON["INFO_CONVERT"] == 1) && (index(type,"MPI_Info") > 0))
            printf"  *%s = MPI_Info_c2f(%sC);\n",para,para

        if ((ENVIRON["OP_CONVERT"] == 1) && (index(type,"MPI_Op") > 0))
            printf"  *%s = MPI_Op_c2f(%sC);\n",para,para

        if ((ENVIRON["TYPE_CONVERT"] == 1) && (index(type,"MPI_Datatype") > 0))
            printf"  *%s = MPI_Type_c2f(%sC);\n",para,para

        if ((ENVIRON["WIN_CONVERT"] == 1) && (index(type,"MPI_Win") > 0))
            printf"  *%s = MPI_Win_c2f(%sC);\n",para,para

        if ((ENVIRON["REQUEST_CONVERT"] == 1) && (index(type,"MPI_Request") > 0))
            printf"  *%s = MPI_Request_c2f(%sC);\n",para,para

        if ((ENVIRON["STATUS_CONVERT"] == 1) && (index(type,"MPI_Status") > 0)) {
            printf"  if ( (%s != VT_MPI_F_STATUS_IGNORE) && (%s != VT_MPI_F_STATUSES_IGNORE) )\n",para,para
            printf"    MPI_Status_c2f(%sC, %s);\n",para,para
        }
    }

    #ARRAY BACK CONVERSION
    if ( ((index(para, "_CLASS_ARRAY_OUT_") != 0) ||
          (index(para, "_CLASS_ARRAY_IO_") != 0))   )
    {
        #both of these classes need array back conversion

        #extract the name of the length parameter
        splitstring="_CLASS_ARRAY_OUT_"
        if (index(para, "_CLASS_ARRAY_IO_") != 0)
            splitstring="_CLASS_ARRAY_IO_"

        split(para,lentemp,splitstring)
        len_parameter = lentemp[2]

        #now we have to handle all the imaginable handles
        if (aint_convert && (index(type,"MPI_Aint") > 0)) {
            printf"  if ( *%s != MPI_UNDEFINED )\n  {\n",len_parameter
            printf"    for (i = 0; i < *%s; i++) \n",len_parameter
            printf"      %s[i] = (MPI_Fint)%sC[i];\n",para,para
            printf"  }\n"
        }

        if ((ENVIRON["COMM_CONVERT"] == 1) && (index(type,"MPI_Comm") > 0)) {
            printf"  if ( *%s != MPI_UNDEFINED )\n  {\n",len_parameter
            printf"    for (i = 0; i < *%s; i++) \n",len_parameter
            printf"      %s[i] = MPI_Comm_c2f(%sC[i]);\n",para,para
            printf"  }\n"
        }

        if ((ENVIRON["ERRH_CONVERT"] == 1) && (index(type,"MPI_Errhandler") > 0)) {
            printf"  if ( *%s != MPI_UNDEFINED )\n  {\n",len_parameter
            printf"    for (i = 0; i < *%s; i++) \n",len_parameter
            printf"      %s[i] = MPI_Errhandler_c2f(%sC[i]);\n",para,para
            printf"  }\n"
        }

        if ((ENVIRON["FILE_CONVERT"] == 1) && (index(type,"MPI_File") > 0)) {
            printf"  if ( *%s != MPI_UNDEFINED )\n  {\n",len_parameter
            printf"    for (i = 0; i < *%s; i++) \n",len_parameter
            printf"      %s[i] = MPI_File_c2f(%sC[i]);\n",para,para
            printf"  }\n"
        }

        if ((ENVIRON["GROUP_CONVERT"] == 1) && (index(type,"MPI_Group") > 0)) {
            printf"  if ( *%s != MPI_UNDEFINED )\n  {\n",len_parameter
            printf"    for (i = 0; i < *%s; i++) \n",len_parameter
            printf"      %s[i] = MPI_Group_c2f(%sC[i]);\n",para,para
            printf"  }\n"
        }

        if ((ENVIRON["INFO_CONVERT"] == 1) && (index(type,"MPI_Info") > 0)) {
            printf"  if ( *%s != MPI_UNDEFINED )\n  {\n",len_parameter
            printf"    for (i = 0; i < *%s; i++) \n",len_parameter
            printf"      %s[i] = MPI_Info_c2f(%sC[i]);\n",para,para
            printf"  }\n"
        }

        if ((ENVIRON["OP_CONVERT"] == 1) && (index(type,"MPI_Op") > 0)) {
            printf"  if ( *%s != MPI_UNDEFINED )\n  {\n",len_parameter
            printf"    for (i = 0; i < *%s; i++) \n",len_parameter
            printf"      %s[i] = MPI_Op_c2f(%sC[i]);\n",para,para
            printf"  }\n"
        }

        if ((ENVIRON["TYPE_CONVERT"] == 1) && (index(type,"MPI_Datatype") > 0)) {
            printf"  if ( *%s != MPI_UNDEFINED )\n  {\n",len_parameter
            printf"    for (i = 0; i < *%s; i++) \n",len_parameter
            printf"      %s[i] = MPI_Type_c2f(%sC[i]);\n",para,para
            printf"  }\n"
        }

        if ((ENVIRON["WIN_CONVERT"] == 1) && (index(type,"MPI_Win") > 0)) {
            printf"  if ( *%s != MPI_UNDEFINED )\n  {\n",len_parameter
            printf"    for (i = 0; i < *%s; i++) \n",len_parameter
            printf"      %s[i] = MPI_Win_c2f(%sC[i]);\n",para,para
            printf"  }\n"
        }

        if ((ENVIRON["REQUEST_CONVERT"] == 1) && (index(type,"MPI_Request") > 0)) {
            printf"  if ( *%s != MPI_UNDEFINED )\n  {\n",len_parameter
            printf"    for (i = 0; i < *%s; i++) \n",len_parameter
            printf"      %s[i] = MPI_Request_c2f(%sC[i]);\n",para,para
            printf"  }\n"
        }

        if ((ENVIRON["STATUS_CONVERT"] == 1) && (index(type,"MPI_Status") > 0)) {
            printf"  if ( (*%s != MPI_UNDEFINED) && (%s != VT_MPI_F_STATUSES_IGNORE) && (%s != VT_MPI_F_STATUS_IGNORE) )\n  {\n",len_parameter,para,para
            printf"    for (i = 0; i < *%s; i++) \n",len_parameter
            printf"      MPI_Status_c2f(&%sC[i], &%s[i*VT_MPI_STATUS_SIZE]);\n",para,para
            printf"  }\n"
        }
    }

    #free the array memory for all but MPI_Status
    if ( (index(para,"_CLASS_ARRAY_") != 0) &&
         (index(type,"MPI_Status") == 0) )
    {
        if ((aint_convert && (index(type,"MPI_Aint") > 0)) ||
           ((ENVIRON["COMM_CONVERT"] == 1) && (index(type,"MPI_Comm") > 0)) ||
           ((ENVIRON["ERRH_CONVERT"] == 1) && (index(type,"MPI_Errhandler") > 0)) ||
           ((ENVIRON["FILE_CONVERT"] == 1) && (index(type,"MPI_File") > 0)) ||
           ((ENVIRON["GROUP_CONVERT"] == 1) && (index(type,"MPI_Group") > 0)) ||
           ((ENVIRON["INFO_CONVERT"] == 1) && (index(type,"MPI_Info") > 0)) ||
           ((ENVIRON["OP_CONVERT"] == 1) && (index(type,"MPI_Op") > 0)) ||
           ((ENVIRON["TYPE_CONVERT"] == 1) && (index(type,"MPI_Datatype") > 0)) ||
           ((ENVIRON["WIN_CONVERT"] == 1) && (index(type,"MPI_Win") > 0)) )
        {
            printf "  free(%sC);\n",para
        }
    }

    #free the array memory for statuses
    if ( (index(para,"_CLASS_ARRAY_") != 0) &&
         (index(type,"MPI_Status") != 0) &&
         (ENVIRON["STATUS_CONVERT"] == 1) )
    {
        printf "  if ( (%s != VT_MPI_F_STATUS_IGNORE) && (%s != VT_MPI_F_STATUSES_IGNORE) )\n",para,para
        printf "    free(%sC);\n",para
    }

    #free Status memory (for single status values)
    if ( (index(para,"_CLASS_SINGLE_") != 0) &&
         (index(type,"MPI_Status") != 0) &&
         (ENVIRON["STATUS_CONVERT"] == 1) )
    {
        printf "  if ( (%s != VT_MPI_F_STATUS_IGNORE) && (%s != VT_MPI_F_STATUSES_IGNORE) )\n",para,para
        printf "    free(%sC);\n",para
    }

    #free string memory
    if ( (index(para,"_CLASS_SINGLE_IN") != 0) &&
         (type == "char*") )
    {
        printf "  free(%sC);\n",para
    }
} #function back_convert

# -------------------------------------------------
# Function printing an variable name depending upon
# its type and temporary representation.
# -------------------------------------------------
function get_converted_name(para,type) {

    #string
    if (type == "char*") return para "C"

    pointer=""
    if (index(type, "*") == 0 && index(para, "[") == 0)
        pointer="*"

    #remove arrays declarations from parameter:
    gsub("[[].*[]]","",para)

    #find out wheter we have to pass address operator "&"
    address=""
    if ((index(para,"_CLASS_SINGLE_") != 0) && (index(type,"MPI_Status") == 0) )
        address="&"

    #handle conversion
    if ((aint_convert && (index(type,"MPI_Aint") > 0)) ||
        ((ENVIRON["COMM_CONVERT"] == 1) && (index(type,"MPI_Comm") > 0)) ||
        ((ENVIRON["ERRH_CONVERT"] == 1) && (index(type,"MPI_Errhandler") > 0)) ||
        ((ENVIRON["FILE_CONVERT"] == 1) && (index(type,"MPI_File") > 0)) ||
        ((ENVIRON["GROUP_CONVERT"] == 1) && (index(type,"MPI_Group") > 0)) ||
        ((ENVIRON["INFO_CONVERT"] == 1) && (index(type,"MPI_Info") > 0)) ||
        ((ENVIRON["OP_CONVERT"] == 1) && (index(type,"MPI_Op") > 0)) ||
        ((ENVIRON["TYPE_CONVERT"] == 1) && (index(type,"MPI_Datatype") > 0)) ||
        ((ENVIRON["WIN_CONVERT"] == 1) && (index(type,"MPI_Win") > 0)) ||
        ((ENVIRON["REQUEST_CONVERT"] == 1) && (index(type,"MPI_Request") > 0)) ||
        (index(type,"MPI_Status") > 0) )
    {
        return address para "C"
    }

    #it is not a handle type so normal handling
    return pointer para
}

# -------------------------------------------------
# Function that converts array indizes passed between 
# C and Fortran, only used for array inidces generated
# in C and passed back to Fortran.
# -------------------------------------------------
function convert_output_array_indices(type,para) {
    #We have three different cases:
    # * _CLASS_ARRAYINDEX_OUT_SINGLE_NOCONDITION
    # * _CLASS_ARRAYINDEX_OUT_SINGLE_CONDITION_conditionargument
    # * _CLASS_ARRAYINDEX_OUT_ARRAY_sizeargument

    #is it the "_CLASS_ARRAYINDEX_OUT_SINGLE_NOCONDITION" case ?
    if (index(para,"_CLASS_ARRAYINDEX_OUT_SINGLE_NOCONDITION") != 0) {
        printf "  if ( (*%s != MPI_UNDEFINED) && (*%s >= 0))\n", para, para
        printf "    (*%s)++;\n", para, para
    }

    #is it the "_CLASS_ARRAYINDEX_OUT_SINGLE_CONDITION_<ARG>" case ?
    if (index(para,"_CLASS_ARRAYINDEX_OUT_SINGLE_CONDITION_") != 0) {
        #extract the name of the "conditionargument" parameter
        splitstring="_CLASS_ARRAYINDEX_OUT_SINGLE_CONDITION_"
        split(para,condtemp,splitstring)
        cond = condtemp[2]

        printf "  if ( (*%s) && (*%s != MPI_UNDEFINED) && (*%s >= 0))\n", cond, para, para
        printf "    (*%s)++;\n", para, para
    }

    #is it the "_CLASS_ARRAYINDEX_OUT_ARRAY_<ARG>" case ?
    if (index(para,"_CLASS_ARRAYINDEX_OUT_ARRAY_") != 0) {
        #extract the name of the "conditionargument" parameter
        splitstring="_CLASS_ARRAYINDEX_OUT_ARRAY_"
        split(para,counttemp,splitstring)
        count = counttemp[2]

        printf "  if ( *%s != MPI_UNDEFINED )\n  {\n", count
        printf "    int j;\n"
        printf "    for (j = 0; j < *%s; j++)\n    {\n", count
        printf "      if ( (%s[j] != MPI_UNDEFINED) && (%s[j] >= 0))\n", para, para
        printf "        %s[j]++;\n    }\n  }\n", para, para
    }
}
End-of-File

@AWK@ -f $tmp.awk -F, <$tmp.tmp >>$tmp.c
if test $? -ne 0; then exit $?; fi
mv $tmp.c $out
rm $tmp.awk

exit 0
